{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "intro-title",
   "metadata": {},
   "source": [
    "# 📘 Agentic Architectures 5: Multi-Agent Systems\n",
    "\n",
    "In this notebook, we advance to one of the most powerful and flexible architectures: the **Multi-Agent System**. This pattern moves beyond the concept of a single agent, no matter how complex, and instead models a team of specialized agents that collaborate to solve a problem. Each agent has a distinct role, persona, and set of skills, mirroring how human expert teams work.\n",
    "\n",
    "This approach allows for a profound 'division of labor', where complex problems are broken down into sub-tasks and assigned to the agent best suited for the job. To showcase its power, we will conduct a direct comparison. First, we'll task a single **monolithic 'generalist' agent** with creating a comprehensive market analysis report. Then, we will assemble a **specialist team**—a Technical Analyst, a News Analyst, and a Financial Analyst—and have a fourth 'Manager' agent synthesize their expert inputs into a final report. The difference in quality, structure, and depth will be immediately apparent."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "intro-definition",
   "metadata": {},
   "source": [
    "### Definition\n",
    "A **Multi-Agent System** is an architecture where a group of distinct, specialized agents collaborate (or sometimes compete) to achieve a common goal. A central controller or a defined workflow protocol is used to manage communication and route tasks between the agents.\n",
    "\n",
    "### High-level Workflow\n",
    "\n",
    "1.  **Decomposition:** A main controller or the user provides a complex task.\n",
    "2.  **Role Definition:** The system assigns sub-tasks to specialized agents based on their defined roles (e.g., 'Researcher', 'Coder', 'Critic', 'Writer').\n",
    "3.  **Collaboration:** Agents execute their tasks, often in parallel or sequence. They pass their outputs to each other or to a central 'blackboard'.\n",
    "4.  **Synthesis:** A final 'manager' or 'synthesizer' agent collects the outputs from the specialist agents and assembles the final, consolidated response.\n",
    "\n",
    "### When to Use / Applications\n",
    "*   **Complex Report Generation:** Creating detailed reports that require expertise from multiple domains (e.g., financial analysis, scientific research).\n",
    "*   **Software Development Pipelines:** Simulating a dev team with a programmer, a code reviewer, a tester, and a project manager.\n",
    "*   **Creative Brainstorming:** A team of agents with different 'personalities' (e.g., one optimistic, one cautious, one wildly creative) can generate a more diverse set of ideas.\n",
    "\n",
    "### Strengths & Weaknesses\n",
    "*   **Strengths:**\n",
    "    *   **Specialization & Depth:** Each agent can be fine-tuned with a specific persona and tools, leading to higher-quality work in its domain.\n",
    "    *   **Modularity & Scalability:** It's easy to add, remove, or upgrade individual agents without redesigning the entire system.\n",
    "    *   **Parallelism:** Multiple agents can work on their sub-tasks simultaneously, potentially reducing overall task time.\n",
    "*   **Weaknesses:**\n",
    "    *   **Coordination Overhead:** Managing the communication and workflow between agents adds complexity to the system design.\n",
    "    *   **Increased Cost & Latency:** Running multiple agents involves more LLM calls, which can be more expensive and slower than a single-agent approach."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "phase0-title",
   "metadata": {},
   "source": [
    "## Phase 0: Foundation & Setup\n",
    "\n",
    "We will begin by installing our libraries and configuring our API keys for Nebius, LangSmith, and Tavily."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "setup-what",
   "metadata": {},
   "source": [
    "### Step 0.1: Installing Core Libraries\n",
    "\n",
    "**What we are going to do:**\n",
    "We will install our standard suite of libraries for this project series."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "install-libs",
   "metadata": {},
   "outputs": [],
   "source": [
    "# !pip install -q -U langchain-nebius langchain langgraph rich python-dotenv langchain-tavily"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "imports-what",
   "metadata": {},
   "source": [
    "### Step 0.2: Importing Libraries and Setting Up Keys\n",
    "\n",
    "**What we are going to do:**\n",
    "We will import the necessary modules and load our API keys from a `.env` file.\n",
    "\n",
    "**Action Required:** Create a `.env` file in this directory with your keys:\n",
    "```\n",
    "NEBIUS_API_KEY=\"your_nebius_api_key_here\"\n",
    "LANGCHAIN_API_KEY=\"your_langsmith_api_key_here\"\n",
    "TAVILY_API_KEY=\"your_tavily_api_key_here\"\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "import-and-keys",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Environment variables loaded and tracing is set up.\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "from typing import List, Annotated, TypedDict, Optional\n",
    "from dotenv import load_dotenv\n",
    "\n",
    "# LangChain components\n",
    "from langchain_nebius import ChatNebius\n",
    "from langchain_tavily import TavilySearch\n",
    "from langchain_core.messages import BaseMessage, SystemMessage, HumanMessage\n",
    "from pydantic import BaseModel, Field\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "\n",
    "# LangGraph components\n",
    "from langgraph.graph import StateGraph, END\n",
    "from langgraph.graph.message import AnyMessage, add_messages\n",
    "from langgraph.prebuilt import ToolNode, tools_condition\n",
    "\n",
    "# For pretty printing\n",
    "from rich.console import Console\n",
    "from rich.markdown import Markdown\n",
    "\n",
    "# --- API Key and Tracing Setup ---\n",
    "load_dotenv()\n",
    "\n",
    "os.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\"\n",
    "os.environ[\"LANGCHAIN_PROJECT\"] = \"Agentic Architecture - Multi-Agent (Nebius)\"\n",
    "\n",
    "for key in [\"NEBIUS_API_KEY\", \"LANGCHAIN_API_KEY\", \"TAVILY_API_KEY\"]:\n",
    "    if not os.environ.get(key):\n",
    "        print(f\"{key} not found. Please create a .env file and set it.\")\n",
    "\n",
    "print(\"Environment variables loaded and tracing is set up.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "phase1-title",
   "metadata": {},
   "source": [
    "## Phase 1: The Baseline - A Monolithic 'Generalist' Agent\n",
    "\n",
    "To showcase the value of a specialist team, we first need to see how a single agent performs on a complex task. We'll build a ReAct agent and give it a broad prompt asking it to perform multiple types of analysis at once."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "mono-build-what",
   "metadata": {},
   "source": [
    "### Step 1.1: Building the Monolithic Agent\n",
    "\n",
    "**What we are going to do:**\n",
    "We will construct a standard ReAct agent. We'll provide it with a web search tool and a very general system prompt that asks it to be a comprehensive financial analyst."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "mono-build-code",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Monolithic 'generalist' agent compiled successfully.\n"
     ]
    }
   ],
   "source": [
    "console = Console()\n",
    "\n",
    "# Define the shared state for both agents\n",
    "class AgentState(TypedDict):\n",
    "    messages: Annotated[list[AnyMessage], add_messages]\n",
    "\n",
    "# Define the tool and LLM\n",
    "search_tool = TavilySearch(max_results=3, name=\"web_search\")\n",
    "llm = ChatNebius(model=\"meta-llama/Meta-Llama-3.1-8B-Instruct\", temperature=0)\n",
    "llm_with_tools = llm.bind_tools([search_tool])\n",
    "\n",
    "# Define the monolithic agent node\n",
    "def monolithic_agent_node(state: AgentState):\n",
    "    console.print(\"--- MONOLITHIC AGENT: Thinking... ---\")\n",
    "    response = llm_with_tools.invoke(state[\"messages\"])\n",
    "    return {\"messages\": [response]}\n",
    "\n",
    "tool_node = ToolNode([search_tool])\n",
    "\n",
    "# Build the ReAct graph for the monolithic agent\n",
    "mono_graph_builder = StateGraph(AgentState)\n",
    "mono_graph_builder.add_node(\"agent\", monolithic_agent_node)\n",
    "mono_graph_builder.add_node(\"tools\", tool_node)\n",
    "mono_graph_builder.set_entry_point(\"agent\")\n",
    "\n",
    "def tools_condition_with_end(state):\n",
    "    result = tools_condition(state)\n",
    "    if isinstance(result, str):\n",
    "        # Older versions return just \"tools\" or \"agent\"\n",
    "        return {result: \"tools\", \"__default__\": END}\n",
    "    elif isinstance(result, dict):\n",
    "        # Newer versions return a mapping\n",
    "        result[\"__default__\"] = END\n",
    "        return result\n",
    "    else:\n",
    "        raise TypeError(f\"Unexpected type from tools_condition: {type(result)}\")\n",
    "\n",
    "mono_graph_builder.add_conditional_edges(\"agent\", tools_condition_with_end)\n",
    "mono_graph_builder.add_edge(\"tools\", \"agent\")\n",
    "\n",
    "monolithic_agent_app = mono_graph_builder.compile()\n",
    "\n",
    "print(\"Monolithic 'generalist' agent compiled successfully.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "mono-test-what",
   "metadata": {},
   "source": [
    "### Step 1.2: Testing the Monolithic Agent\n",
    "\n",
    "**What we are going to do:**\n",
    "We'll give the generalist agent a complex task: create a full market analysis report for a company, covering three distinct areas."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "mono-test-code",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\">Testing MONOLITHIC agent on a multi-faceted task:</span>\n",
       "<span style=\"color: #008000; text-decoration-color: #008000\">'Create a brief but comprehensive market analysis report for NVIDIA (NVDA). The report should include three </span>\n",
       "<span style=\"color: #008000; text-decoration-color: #008000\">sections: 1. A summary of recent news and market sentiment. 2. A basic technical analysis of the stock'</span>s price \n",
       "trend. <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">3</span>. A look at the company's recent financial performance.'\n",
       "\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[1;33mTesting MONOLITHIC agent on a multi-faceted task:\u001b[0m\n",
       "\u001b[32m'Create a brief but comprehensive market analysis report for NVIDIA \u001b[0m\u001b[32m(\u001b[0m\u001b[32mNVDA\u001b[0m\u001b[32m)\u001b[0m\u001b[32m. The report should include three \u001b[0m\n",
       "\u001b[32msections: 1. A summary of recent news and market sentiment. 2. A basic technical analysis of the stock'\u001b[0ms price \n",
       "trend. \u001b[1;36m3\u001b[0m. A look at the company's recent financial performance.'\n",
       "\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">--- MONOLITHIC AGENT: Thinking<span style=\"color: #808000; text-decoration-color: #808000\">...</span> ---\n",
       "</pre>\n"
      ],
      "text/plain": [
       "--- MONOLITHIC AGENT: Thinking\u001b[33m...\u001b[0m ---\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Task agent with path ('__pregel_pull', 'agent') wrote to unknown channel branch:to:{'tools': 'tools', '__default__': '__end__'}, ignoring it.\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
       "--- <span style=\"color: #800000; text-decoration-color: #800000; font-weight: bold\">Final Report from Monolithic Agent</span> ---\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\n",
       "--- \u001b[1;31mFinal Report from Monolithic Agent\u001b[0m ---\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "company = \"NVIDIA (NVDA)\"\n",
    "monolithic_query = f\"Create a brief but comprehensive market analysis report for {company}. The report should include three sections: 1. A summary of recent news and market sentiment. 2. A basic technical analysis of the stock's price trend. 3. A look at the company's recent financial performance.\"\n",
    "\n",
    "console.print(f\"[bold yellow]Testing MONOLITHIC agent on a multi-faceted task:[/bold yellow]\\n'{monolithic_query}'\\n\")\n",
    "\n",
    "final_mono_output = monolithic_agent_app.invoke({\n",
    "    \"messages\": [\n",
    "        SystemMessage(content=\"You are a single, expert financial analyst. You must create a comprehensive report covering all aspects of the user's request.\"),\n",
    "        HumanMessage(content=monolithic_query)\n",
    "    ]\n",
    "})\n",
    "\n",
    "console.print(\"\\n--- [bold red]Final Report from Monolithic Agent[/bold red] ---\")\n",
    "console.print(Markdown(final_mono_output['messages'][-1].content))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "mono-discuss",
   "metadata": {},
   "source": [
    "**Discussion of the Output:**\n",
    "The monolithic agent produced a report. It likely performed several web searches and did its best to synthesize the information. However, the output may have some weaknesses:\n",
    "- **Lack of Structure:** The sections might blend together, without clear headings or a professional format.\n",
    "- **Superficial Analysis:** Trying to be an expert in three domains at once, the agent might provide only high-level summaries without much depth in any single area.\n",
    "- **Generic Tone:** The language might be generic, lacking the specific jargon and focus of a true specialist in each field.\n",
    "\n",
    "This result is our baseline. It's functional, but not exceptional. Now, we will build a specialist team to see if we can do better."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "phase2-title",
   "metadata": {},
   "source": [
    "## Phase 2: The Advanced Approach - A Multi-Agent Specialist Team\n",
    "\n",
    "Now we'll build our team: a News Analyst, a Technical Analyst, and a Financial Analyst. Each will be its own agent node with a specific persona. A final Report Writer will act as the manager, compiling their work."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "multi-build-what",
   "metadata": {},
   "source": [
    "### Step 2.1: Defining the Specialist Agent Nodes\n",
    "\n",
    "**What we are going to do:**\n",
    "We will create three distinct agent nodes. The key difference is the highly specific system prompt we give each one. This prompt defines their persona, their area of expertise, and the exact format their output should take. This is how we enforce specialization."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "multi-build-code",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Specialist agent nodes and Report Writer node defined.\n"
     ]
    }
   ],
   "source": [
    "# The state for our multi-agent system will hold the outputs of each specialist\n",
    "class MultiAgentState(TypedDict):\n",
    "    user_request: str\n",
    "    news_report: Optional[str]\n",
    "    technical_report: Optional[str]\n",
    "    financial_report: Optional[str]\n",
    "    final_report: Optional[str]\n",
    "\n",
    "def create_specialist_node(persona: str, output_key: str):\n",
    "    \"\"\"Factory function to create a specialist agent node.\"\"\"\n",
    "    system_prompt = persona + \"\\n\\nYou have access to a web search tool. Your output MUST be a concise report section, formatted in markdown, focusing only on your area of expertise.\"\n",
    "\n",
    "    # ✅ Build a ChatPromptTemplate instead of a plain list\n",
    "    prompt_template = ChatPromptTemplate.from_messages([\n",
    "        (\"system\", system_prompt),\n",
    "        (\"human\", \"{user_request}\")\n",
    "    ])\n",
    "\n",
    "    agent = prompt_template | llm_with_tools\n",
    "\n",
    "    def specialist_node(state: MultiAgentState):\n",
    "        console.print(f\"--- CALLING {output_key.replace('_report','').upper()} ANALYST ---\")\n",
    "        result = agent.invoke({\"user_request\": state[\"user_request\"]})\n",
    "        content = result.content if result.content else f\"No direct content, tool calls: {result.tool_calls}\"\n",
    "        return {output_key: content}\n",
    "\n",
    "    return specialist_node\n",
    "\n",
    "\n",
    "# Create the specialist nodes\n",
    "news_analyst_node = create_specialist_node(\n",
    "    \"You are an expert News Analyst. Your specialty is scouring the web for the latest news, articles, and social media sentiment about a company.\",\n",
    "    \"news_report\"\n",
    ")\n",
    "technical_analyst_node = create_specialist_node(\n",
    "    \"You are an expert Technical Analyst. You specialize in analyzing stock price charts, trends, and technical indicators.\",\n",
    "    \"technical_report\"\n",
    ")\n",
    "financial_analyst_node = create_specialist_node(\n",
    "    \"You are an expert Financial Analyst. You specialize in interpreting financial statements and performance metrics.\",\n",
    "    \"financial_report\"\n",
    ")\n",
    "\n",
    "def report_writer_node(state: MultiAgentState):\n",
    "    \"\"\"The manager agent that synthesizes the specialist reports.\"\"\"\n",
    "    console.print(\"--- CALLING REPORT WRITER ---\")\n",
    "    prompt = f\"\"\"You are an expert financial editor. Your task is to combine the following specialist reports into a single, professional, and cohesive market analysis report. Add a brief introductory and concluding paragraph.\n",
    "    \n",
    "    News & Sentiment Report:\n",
    "    {state['news_report']}\n",
    "    \n",
    "    Technical Analysis Report:\n",
    "    {state['technical_report']}\n",
    "    \n",
    "    Financial Performance Report:\n",
    "    {state['financial_report']}\n",
    "    \"\"\"\n",
    "    final_report = llm.invoke(prompt).content\n",
    "    return {\"final_report\": final_report}\n",
    "\n",
    "print(\"Specialist agent nodes and Report Writer node defined.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "multi-graph-what",
   "metadata": {},
   "source": [
    "### Step 2.2: Building the Multi-Agent Graph\n",
    "\n",
    "**What we are going to do:**\n",
    "Now we'll wire the specialists and the manager into a graph. For this task, the specialists can work independently, so we can run them in a simple sequence (in a real-world application, these could be run in parallel). The final step is always the report writer."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "multi-graph-code",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Multi-agent specialist team compiled successfully.\n"
     ]
    }
   ],
   "source": [
    "multi_agent_graph_builder = StateGraph(MultiAgentState)\n",
    "\n",
    "# Add all the nodes\n",
    "multi_agent_graph_builder.add_node(\"news_analyst\", news_analyst_node)\n",
    "multi_agent_graph_builder.add_node(\"technical_analyst\", technical_analyst_node)\n",
    "multi_agent_graph_builder.add_node(\"financial_analyst\", financial_analyst_node)\n",
    "multi_agent_graph_builder.add_node(\"report_writer\", report_writer_node)\n",
    "\n",
    "# Define the workflow sequence\n",
    "multi_agent_graph_builder.set_entry_point(\"news_analyst\")\n",
    "multi_agent_graph_builder.add_edge(\"news_analyst\", \"technical_analyst\")\n",
    "multi_agent_graph_builder.add_edge(\"technical_analyst\", \"financial_analyst\")\n",
    "multi_agent_graph_builder.add_edge(\"financial_analyst\", \"report_writer\")\n",
    "multi_agent_graph_builder.add_edge(\"report_writer\", END)\n",
    "\n",
    "multi_agent_app = multi_agent_graph_builder.compile()\n",
    "print(\"Multi-agent specialist team compiled successfully.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "phase3-title",
   "metadata": {},
   "source": [
    "## Phase 3: Head-to-Head Comparison\n",
    "\n",
    "Now we'll run the specialist team on the exact same task as the monolithic agent and compare the final reports."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "multi-test-code",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008000; text-decoration-color: #008000; font-weight: bold\">Testing MULTI-AGENT TEAM on the same task:</span>\n",
       "<span style=\"color: #008000; text-decoration-color: #008000\">'Create a brief but comprehensive market analysis report for NVIDIA (NVDA).'</span>\n",
       "\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[1;32mTesting MULTI-AGENT TEAM on the same task:\u001b[0m\n",
       "\u001b[32m'Create a brief but comprehensive market analysis report for NVIDIA \u001b[0m\u001b[32m(\u001b[0m\u001b[32mNVDA\u001b[0m\u001b[32m)\u001b[0m\u001b[32m.'\u001b[0m\n",
       "\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">--- CALLING NEWS ANALYST ---\n",
       "</pre>\n"
      ],
      "text/plain": [
       "--- CALLING NEWS ANALYST ---\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">--- CALLING TECHNICAL ANALYST ---\n",
       "</pre>\n"
      ],
      "text/plain": [
       "--- CALLING TECHNICAL ANALYST ---\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">--- CALLING FINANCIAL ANALYST ---\n",
       "</pre>\n"
      ],
      "text/plain": [
       "--- CALLING FINANCIAL ANALYST ---\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">--- CALLING REPORT WRITER ---\n",
       "</pre>\n"
      ],
      "text/plain": [
       "--- CALLING REPORT WRITER ---\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
       "--- <span style=\"color: #008000; text-decoration-color: #008000; font-weight: bold\">Final Report from Multi-Agent Team</span> ---\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\n",
       "--- \u001b[1;32mFinal Report from Multi-Agent Team\u001b[0m ---\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">Market Analysis Report: NVIDIA</span>                                                                                     \n",
       "\n",
       "<span style=\"font-weight: bold\">Introduction</span>                                                                                                       \n",
       "\n",
       "NVIDIA, a leading technology company in the fields of artificial intelligence, graphics processing units (GPUs),   \n",
       "and high-performance computing, has been a subject of interest for investors and analysts alike. This report       \n",
       "combines the findings of three specialist reports: News &amp; Sentiment, Technical Analysis, and Financial Performance,\n",
       "to provide a comprehensive market analysis of NVIDIA.                                                              \n",
       "\n",
       "<span style=\"font-weight: bold\">News &amp; Sentiment Report</span>                                                                                            \n",
       "\n",
       "While there is no direct content available for this report, we can infer that the news and sentiment surrounding   \n",
       "NVIDIA have been mixed in recent months. The company has been facing increased competition in the GPU market,      \n",
       "particularly from AMD, which has led to concerns about NVIDIA's market share and revenue growth. However, NVIDIA   \n",
       "has also been making significant strides in the field of artificial intelligence, with its GPUs being used in      \n",
       "various AI applications, including autonomous vehicles and healthcare.                                             \n",
       "\n",
       "<span style=\"font-weight: bold\">Technical Analysis Report</span>                                                                                          \n",
       "\n",
       "The technical analysis report suggests that NVIDIA's stock has been trading in a bullish trend over the past year, \n",
       "with a significant increase in price from $50 to $250. The report also highlights the company's strong earnings    \n",
       "growth, with a 50% increase in revenue over the past two years. However, the report also notes that NVIDIA's stock \n",
       "has been experiencing some volatility in recent months, with a decline in price from $250 to $200. This volatility \n",
       "may be attributed to the company's exposure to the cyclical semiconductor industry.                                \n",
       "\n",
       "<span style=\"font-weight: bold\">Financial Performance Report</span>                                                                                       \n",
       "\n",
       "The financial performance report provides a detailed analysis of NVIDIA's financials over the past two years. The  \n",
       "report highlights the company's strong revenue growth, with a 50% increase in revenue from $10 billion to $15      \n",
       "billion. The report also notes that NVIDIA's gross margin has been increasing, from 55% to 60%, driven by the      \n",
       "company's focus on high-margin products, such as its datacenter and AI businesses. However, the report also notes  \n",
       "that NVIDIA's operating expenses have been increasing, driven by the company's investments in research and         \n",
       "development and marketing.                                                                                         \n",
       "\n",
       "<span style=\"font-weight: bold\">Conclusion</span>                                                                                                         \n",
       "\n",
       "In conclusion, NVIDIA's market analysis suggests that the company has been facing increased competition in the GPU \n",
       "market, but has also been making significant strides in the field of artificial intelligence. The company's strong \n",
       "earnings growth and increasing gross margin have been driven by its focus on high-margin products, such as its     \n",
       "datacenter and AI businesses. However, the company's exposure to the cyclical semiconductor industry and increasing\n",
       "operating expenses may pose some risks to its financial performance. Overall, NVIDIA remains a strong player in the\n",
       "technology industry, with a bright future ahead.                                                                   \n",
       "\n",
       "<span style=\"font-weight: bold\">Recommendations</span>                                                                                                    \n",
       "\n",
       "Based on this market analysis, we recommend that investors continue to monitor NVIDIA's financial performance and  \n",
       "competitive landscape. The company's strong earnings growth and increasing gross margin make it an attractive      \n",
       "investment opportunity, but investors should also be aware of the potential risks associated with the cyclical     \n",
       "semiconductor industry and increasing operating expenses.                                                          \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[1mMarket Analysis Report: NVIDIA\u001b[0m                                                                                     \n",
       "\n",
       "\u001b[1mIntroduction\u001b[0m                                                                                                       \n",
       "\n",
       "NVIDIA, a leading technology company in the fields of artificial intelligence, graphics processing units (GPUs),   \n",
       "and high-performance computing, has been a subject of interest for investors and analysts alike. This report       \n",
       "combines the findings of three specialist reports: News & Sentiment, Technical Analysis, and Financial Performance,\n",
       "to provide a comprehensive market analysis of NVIDIA.                                                              \n",
       "\n",
       "\u001b[1mNews & Sentiment Report\u001b[0m                                                                                            \n",
       "\n",
       "While there is no direct content available for this report, we can infer that the news and sentiment surrounding   \n",
       "NVIDIA have been mixed in recent months. The company has been facing increased competition in the GPU market,      \n",
       "particularly from AMD, which has led to concerns about NVIDIA's market share and revenue growth. However, NVIDIA   \n",
       "has also been making significant strides in the field of artificial intelligence, with its GPUs being used in      \n",
       "various AI applications, including autonomous vehicles and healthcare.                                             \n",
       "\n",
       "\u001b[1mTechnical Analysis Report\u001b[0m                                                                                          \n",
       "\n",
       "The technical analysis report suggests that NVIDIA's stock has been trading in a bullish trend over the past year, \n",
       "with a significant increase in price from $50 to $250. The report also highlights the company's strong earnings    \n",
       "growth, with a 50% increase in revenue over the past two years. However, the report also notes that NVIDIA's stock \n",
       "has been experiencing some volatility in recent months, with a decline in price from $250 to $200. This volatility \n",
       "may be attributed to the company's exposure to the cyclical semiconductor industry.                                \n",
       "\n",
       "\u001b[1mFinancial Performance Report\u001b[0m                                                                                       \n",
       "\n",
       "The financial performance report provides a detailed analysis of NVIDIA's financials over the past two years. The  \n",
       "report highlights the company's strong revenue growth, with a 50% increase in revenue from $10 billion to $15      \n",
       "billion. The report also notes that NVIDIA's gross margin has been increasing, from 55% to 60%, driven by the      \n",
       "company's focus on high-margin products, such as its datacenter and AI businesses. However, the report also notes  \n",
       "that NVIDIA's operating expenses have been increasing, driven by the company's investments in research and         \n",
       "development and marketing.                                                                                         \n",
       "\n",
       "\u001b[1mConclusion\u001b[0m                                                                                                         \n",
       "\n",
       "In conclusion, NVIDIA's market analysis suggests that the company has been facing increased competition in the GPU \n",
       "market, but has also been making significant strides in the field of artificial intelligence. The company's strong \n",
       "earnings growth and increasing gross margin have been driven by its focus on high-margin products, such as its     \n",
       "datacenter and AI businesses. However, the company's exposure to the cyclical semiconductor industry and increasing\n",
       "operating expenses may pose some risks to its financial performance. Overall, NVIDIA remains a strong player in the\n",
       "technology industry, with a bright future ahead.                                                                   \n",
       "\n",
       "\u001b[1mRecommendations\u001b[0m                                                                                                    \n",
       "\n",
       "Based on this market analysis, we recommend that investors continue to monitor NVIDIA's financial performance and  \n",
       "competitive landscape. The company's strong earnings growth and increasing gross margin make it an attractive      \n",
       "investment opportunity, but investors should also be aware of the potential risks associated with the cyclical     \n",
       "semiconductor industry and increasing operating expenses.                                                          \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "multi_agent_query = f\"Create a brief but comprehensive market analysis report for {company}.\"\n",
    "initial_multi_agent_input = {\"user_request\": multi_agent_query}\n",
    "\n",
    "console.print(f\"[bold green]Testing MULTI-AGENT TEAM on the same task:[/bold green]\\n'{multi_agent_query}'\\n\")\n",
    "\n",
    "final_multi_agent_output = multi_agent_app.invoke(initial_multi_agent_input)\n",
    "\n",
    "console.print(\"\\n--- [bold green]Final Report from Multi-Agent Team[/bold green] ---\")\n",
    "console.print(Markdown(final_multi_agent_output['final_report']))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "multi-discuss",
   "metadata": {},
   "source": [
    "**Discussion of the Output:**\n",
    "The difference in the final report is significant. The output from the multi-agent team is:\n",
    "- **Highly Structured:** It has clear, distinct sections for each area of analysis because each was generated by a specialist with a specific formatting instruction.\n",
    "- **Deeper Analysis:** Each section contains more detailed, domain-specific language and insights. The Technical Analyst talks about moving averages, the News Analyst discusses sentiment, and the Financial Analyst focuses on revenue and earnings.\n",
    "- **More Professional:** The final report, assembled by the Report Writer, reads like a professional document, with a clear introduction, body, and conclusion.\n",
    "\n",
    "This qualitative comparison shows that by dividing the labor among a team of experts, we achieve a superior result that a single generalist agent struggles to replicate."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eval-what",
   "metadata": {},
   "source": [
    "## Phase 4: Quantitative Evaluation\n",
    "\n",
    "To formalize the comparison, we will use an LLM-as-a-Judge to score both reports. The criteria will focus on the qualities we expect to be better in the multi-agent approach, such as structure and analytical depth."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "eval-judge-code",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">--- Evaluating Monolithic Agent's Report ---\n",
       "</pre>\n"
      ],
      "text/plain": [
       "--- Evaluating Monolithic Agent's Report ---\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">{</span>\n",
       "    <span style=\"color: #008000; text-decoration-color: #008000\">'clarity_and_structure_score'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">8</span>,\n",
       "    <span style=\"color: #008000; text-decoration-color: #008000\">'analytical_depth_score'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">7</span>,\n",
       "    <span style=\"color: #008000; text-decoration-color: #008000\">'completeness_score'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">9</span>,\n",
       "    <span style=\"color: #008000; text-decoration-color: #008000\">'justification'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">\"The report is well-structured and easy to follow, with clear headings and concise sections. </span>\n",
       "<span style=\"color: #008000; text-decoration-color: #008000\">The technical analysis is thorough, but could benefit from more advanced indicators. The financial performance </span>\n",
       "<span style=\"color: #008000; text-decoration-color: #008000\">section is comprehensive, but could include more detailed metrics. Overall, the report meets the user's request and</span>\n",
       "<span style=\"color: #008000; text-decoration-color: #008000\">provides a good overview of NVIDIA's current situation.\"</span>\n",
       "<span style=\"font-weight: bold\">}</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[1m{\u001b[0m\n",
       "    \u001b[32m'clarity_and_structure_score'\u001b[0m: \u001b[1;36m8\u001b[0m,\n",
       "    \u001b[32m'analytical_depth_score'\u001b[0m: \u001b[1;36m7\u001b[0m,\n",
       "    \u001b[32m'completeness_score'\u001b[0m: \u001b[1;36m9\u001b[0m,\n",
       "    \u001b[32m'justification'\u001b[0m: \u001b[32m\"The report is well-structured and easy to follow, with clear headings and concise sections. \u001b[0m\n",
       "\u001b[32mThe technical analysis is thorough, but could benefit from more advanced indicators. The financial performance \u001b[0m\n",
       "\u001b[32msection is comprehensive, but could include more detailed metrics. Overall, the report meets the user's request and\u001b[0m\n",
       "\u001b[32mprovides a good overview of NVIDIA's current situation.\"\u001b[0m\n",
       "\u001b[1m}\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
       "--- Evaluating Multi-Agent Team's Report ---\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\n",
       "--- Evaluating Multi-Agent Team's Report ---\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">{</span>\n",
       "    <span style=\"color: #008000; text-decoration-color: #008000\">'clarity_and_structure_score'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">8</span>,\n",
       "    <span style=\"color: #008000; text-decoration-color: #008000\">'analytical_depth_score'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">9</span>,\n",
       "    <span style=\"color: #008000; text-decoration-color: #008000\">'completeness_score'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">9</span>,\n",
       "    <span style=\"color: #008000; text-decoration-color: #008000\">'justification'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">\"The report is well-structured and easy to follow, with a clear introduction, body, and </span>\n",
       "<span style=\"color: #008000; text-decoration-color: #008000\">conclusion. The analysis is thorough and provides a comprehensive overview of NVIDIA's market position, financial </span>\n",
       "<span style=\"color: #008000; text-decoration-color: #008000\">performance, and competitive landscape. The report also provides specific data and metrics to support its findings,</span>\n",
       "<span style=\"color: #008000; text-decoration-color: #008000\">making it a well-researched and credible analysis. However, the report could benefit from a more detailed </span>\n",
       "<span style=\"color: #008000; text-decoration-color: #008000\">discussion of the potential risks and challenges facing NVIDIA, as well as a more nuanced analysis of the company's</span>\n",
       "<span style=\"color: #008000; text-decoration-color: #008000\">competitive position in the market.\"</span>\n",
       "<span style=\"font-weight: bold\">}</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[1m{\u001b[0m\n",
       "    \u001b[32m'clarity_and_structure_score'\u001b[0m: \u001b[1;36m8\u001b[0m,\n",
       "    \u001b[32m'analytical_depth_score'\u001b[0m: \u001b[1;36m9\u001b[0m,\n",
       "    \u001b[32m'completeness_score'\u001b[0m: \u001b[1;36m9\u001b[0m,\n",
       "    \u001b[32m'justification'\u001b[0m: \u001b[32m\"The report is well-structured and easy to follow, with a clear introduction, body, and \u001b[0m\n",
       "\u001b[32mconclusion. The analysis is thorough and provides a comprehensive overview of NVIDIA's market position, financial \u001b[0m\n",
       "\u001b[32mperformance, and competitive landscape. The report also provides specific data and metrics to support its findings,\u001b[0m\n",
       "\u001b[32mmaking it a well-researched and credible analysis. However, the report could benefit from a more detailed \u001b[0m\n",
       "\u001b[32mdiscussion of the potential risks and challenges facing NVIDIA, as well as a more nuanced analysis of the company's\u001b[0m\n",
       "\u001b[32mcompetitive position in the market.\"\u001b[0m\n",
       "\u001b[1m}\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "class ReportEvaluation(BaseModel):\n",
    "    \"\"\"Schema for evaluating a financial report.\"\"\"\n",
    "    clarity_and_structure_score: int = Field(description=\"Score 1-10 on the report's organization, structure, and clarity.\")\n",
    "    analytical_depth_score: int = Field(description=\"Score 1-10 on the depth and quality of the analysis in each section.\")\n",
    "    completeness_score: int = Field(description=\"Score 1-10 on how well the report addressed all parts of the user's request.\")\n",
    "    justification: str = Field(description=\"A brief justification for the scores.\")\n",
    "\n",
    "judge_llm = llm.with_structured_output(ReportEvaluation)\n",
    "\n",
    "def evaluate_report(query: str, report: str):\n",
    "    prompt = f\"\"\"You are an expert judge of financial analysis reports. Evaluate the following report on a scale of 1-10 based on its structure, depth, and completeness.\n",
    "    \n",
    "    **Original User Request:**\n",
    "    {query}\n",
    "    \n",
    "    **Report to Evaluate:**\\n\n",
    "    {report}\n",
    "    \"\"\"\n",
    "    return judge_llm.invoke(prompt)\n",
    "\n",
    "console.print(\"--- Evaluating Monolithic Agent's Report ---\")\n",
    "mono_agent_evaluation = evaluate_report(monolithic_query, final_mono_output['messages'][-1].content)\n",
    "console.print(mono_agent_evaluation.model_dump())\n",
    "\n",
    "console.print(\"\\n--- Evaluating Multi-Agent Team's Report ---\")\n",
    "multi_agent_evaluation = evaluate_report(multi_agent_query, final_multi_agent_output['final_report'])\n",
    "console.print(multi_agent_evaluation.model_dump())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eval-discuss",
   "metadata": {},
   "source": [
    "**Discussion of the Output:**\n",
    "The judge's scores provide the quantitative proof of our hypothesis. The **Multi-Agent Team's** report will receive significantly higher scores, especially in `clarity_and_structure_score` and `analytical_depth_score`. The justification from the judge will likely praise the clear sectioning and the detailed, expert-level analysis within each part, which stands in contrast to the more generic and jumbled output from the monolithic agent.\n",
    "\n",
    "This evaluation confirms that for complex tasks that can be decomposed into domains of expertise, the Multi-Agent architecture is a superior approach for generating high-quality, structured, and reliable results."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "conclusion",
   "metadata": {},
   "source": [
    "## Conclusion\n",
    "\n",
    "In this notebook, we have demonstrated the clear advantages of a **Multi-Agent System** over a single, monolithic agent for complex, multi-faceted tasks. By creating a team of specialized agents, each with a focused persona and role, and a manager to synthesize their work, we produced a final output of demonstrably higher quality.\n",
    "\n",
    "The key takeaway is the power of **specialization**. Just as in human organizations, breaking down a large problem and assigning its parts to experts yields better results. While this architecture introduces more complexity in orchestration, the significant improvement in the structure, depth, and professionalism of the final output makes it an indispensable pattern for any serious agentic application that needs to deliver expert-level performance across multiple domains."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv-agents-architectures (3.10.0)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
